/*
 * Copyright (c) 2006-2021, Ulandlink Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2022-11-09     zkw         first version
 */
#ifndef __APP_OCPP_FILE_HANLE_H__
#define __APP_OCPP_FILE_HANLE_H__

#ifdef __cplusplus
extern "C" {
#endif

#include <rtthread.h>
#include "os_types.h"
#include "app_ocpp_param.h"
#include "app_application_param.h"
#define CUSTOM_FILE_STORAGE_MAX 5 // 9000
#define FILE_STORAGE_MAX 100
#define LOCAL_AUTH_LIST "Local_Authorization_List.db"
#define AUTH_CACHE "Authorization_Cache.db"
#define OCPP_OFFLINE_CHRAGE "Ocpp_Tran_Cache.db"
#define OCPP_KEY_USER "Ocpp_Key_User.db"
#define OCPP_KEY_CHAR_USER "Ocpp_Key_User_Char.db"

// typedef enum {
//	OCPP_START_CACHE,
//	OCPP_STOP_CACHE,
// }ocpp_tran_cache_e;

// typedef struct{
//
//	ocpp_tran_cache_e							cache_type; 		//
//	char idtag[IdTokenType];							//idtag
//	uint32_t mater_value;									//??����??
//	time_t date_time;											//?��??
//	uint32_t tran_id;											//????ID
//	uint8_t reason;												//?��?????��
//
// }ocpp_tran_data;

// typedef struct{
//
//	ocpp_tran_data tran_info[20];
// }ocpp_tran_data_all;

typedef struct {
    uint8_t idtag[IdTokenType];
    uint32_t expirydate;            // ����Ȩ����ɾ��ʱ��
    uint8_t parent_id[IdTokenType]; // ��������
    authorization_status status;    // ��Ȩ��֤״̬
} ocpp_local_list_t;

/*
function: ocpp_file_storage_remove
description:
    file_name: The storage file that you created
    file_fp:   The FILE pointer that returned by fopen()
    data: The variable which you defined, e.g. struct xxxxx data = {0};  or int data = 0;
    key:  The member of the struct which you use is defined as the only key
    value: The value of the key, e.g. data.id

    When this macro is called successfully, file_fp will be closed by fclose(file_fp), if needed, fopen again.
    Remark: This macro is neither multi-task nor thread safe.
*/
#define ocpp_file_storage_remove(file_name, file_fp, data, key, value)      \
    do {                                                                    \
        int index = 0;                                                      \
        int file_size = 0;                                                  \
        int num = 0;                                                        \
        typeof(data) d = {0};                                               \
        if (!file_fp) {                                                     \
            LOG_E("create file temp.db failed");                            \
            break;                                                          \
        }                                                                   \
        fseek(file_fp, 0, SEEK_END);                                        \
        file_size = ftell(file_fp);                                         \
        num = (file_size - sizeof(index)) / sizeof(typeof(data));           \
        if (num <= 0) {                                                     \
            break;                                                          \
        }                                                                   \
        fseek(file_fp, 0, SEEK_SET);                                        \
        fread(&index, sizeof(index), 1, file_fp);                           \
        FILE *_fp = fopen("_tmp.db", "w+");                                 \
        if (!_fp) {                                                         \
            break;                                                          \
        }                                                                   \
        if (fwrite(&index, sizeof(index), 1, _fp) != 1) {                   \
            LOG_E("write %s failed, line:%d", file_name, __LINE__);         \
        }                                                                   \
        for (int i = 0; i < num; i++) {                                     \
            fread(&d, sizeof(typeof(data)), 1, file_fp);                    \
            if (d.key != value) {                                           \
                if (fwrite(&d, sizeof(typeof(data)), 1, _fp) != 1) {        \
                    LOG_E("write %s failed, line:%d", file_name, __LINE__); \
                }                                                           \
            } else {                                                        \
                LOG_D("delete id = %#x , line:%d", value, __LINE__);        \
            }                                                               \
        }                                                                   \
        fclose(file_fp);                                                    \
        fclose(_fp);                                                        \
        unlink(file_name);                                                  \
        rename("_tmp.db", file_name);                                       \
    } while (0)

bool ocpp_file_storage_init(const char *__restrict file_name);
bool ocpp_file_storage_write(FILE *fp, void *data, uint32_t size);
bool ocpp_key_modify(FILE *fp, void *data, uint32_t position, uint16_t data_size);
bool customization_ocpp_file_storage_write(FILE *fp, void *data, uint32_t size);
bool customization_ocpp_file_storage_init(const char *__restrict file_name);
bool customization_ocpp_file_reset(const char *__restrict file_name);
bool customization_ocpp_file_storage_read(FILE *fp, charge_save_data_info *data, int *read_num);
#ifdef __cplusplus
}
#endif

#endif
